#pragma once
#include "Socket.hpp"
#include "Com.hpp"
#include "Log.hpp"
#include "InetAddr.hpp"
#include <functional>
#include <memory>
#include <unordered_map>
#include <sstream>
#include "Util.hpp"
#include "TcpServer.hpp"

const static std::string gblankline = "\r\n";
const static std::string sep = " ";
const static std::string glinesep = ": ";
const static std::string webroot = "./wwwroot";
const static std::string homepage = "/index.html";

class HttpRequest
{
    public:
    HttpRequest()
        :_blankline(gblankline)
    {

    }
    std::string Serialize()
    {
        return std::string();
    }

    void ParseReqline(std::string& reqline)
    {
        std::stringstream ss;
        ss >> _method >> _uri >>_version;
    }

   bool Deserialize(std::string message)
    {
        std::string out;
        bool n = Util::ReadOneLine(message , &out , sep);
        if(!n)
        {
            LOG(LogLevel::ERROR) << "read on line error";
            return false;
        }
        ParseReqline(out);

        LOG(LogLevel::DEBUG) <<_method;
        LOG(LogLevel::DEBUG) <<_uri;
        LOG(LogLevel::DEBUG) <<_version;
        if(_uri == "/")
        {
            _uri = webroot + "/" + homepage;
        }
        else
        {
            _uri = webroot + _uri;
        }
        return true;

    }

    std::string Uri()
    {
        return _uri;
    }
    private:
    std::string _method;
    std::string _uri;
    std::string _version;
    std::unordered_map<std::string ,std::string> _headers;
    std::string _blankline;
    std::string _text;
};


class HttpResponse
{
    public:
    HttpResponse()
        :_blankspace(gblankline)
    {

    }
    std::string Serialize()
    {
        std::string status_line = _version  +  sep + std::to_string(_status_code) + sep + _status_desc + gblankline;
        for(auto iter : _headers)
        {
            status_line += iter.first ;
            status_line += glinesep ;
            status_line += iter.second;
            status_line += gblankline;
        }
        std::string package = status_line + gblankline + _text;
        std::cout <<package <<std::endl;
        return package;
    }
    bool Deserialize(std::string str)
    {
        return true;
    }

    void SetTargetFile(const std::string& targetfile)
    {
        _targetfile = targetfile;
    }
    bool MakeResponse()
    {
        bool res = Util::ReadFileContent(_targetfile , &_text);
        if(!res)
        {
            _status_code = 404;
            _status_desc = "Not Found";
            return false;
        }
        return true;
    }
    ~HttpResponse()
    {

    }
    public:
    std::string _version;
    int _status_code;
    std::string _status_desc;
    std::unordered_map<std::string ,std::string> _headers;
    std::string _blankspace;
    std::string _text;
    std::string _targetfile;
};


class Http
{
    public:
    Http(uint16_t port)
        :tsvrp(std::make_unique<TcpServer>(port))
    {

    }
    void HandlerHttpRequest(std::shared_ptr<Socket> sock , InetAddr& client)
    {
       
        std::string httpreqstr;
        // 假设：概率大，读到了完整的请求
        sock->Recv(&httpreqstr); // 浏览器给我发过来的是一个大的http字符串, 其实我们的recv也是有问题的。tcp是面向字节流的.
        std::cout << httpreqstr;

        // 直接构建http应答. 内存级别+固定
        HttpResponse resp;
        resp._version = "HTTP/1.1";
        resp._status_code = 200; // success
        resp._status_desc = "OK";

        std::string filename = webroot + homepage; // "./wwwroot/index.html";
        bool res = Util::ReadFileContent(filename, &(resp._text));
        (void)res;
        std::string response_str = resp.Serialize();
        std::cout <<response_str <<std::endl;
        sock->Send(response_str);

    }
    ~Http()
    {

    }
    void Start()
    {
        tsvrp->Start([this](std::shared_ptr<Socket> sock , InetAddr client){
            this->HandlerHttpRequest(sock ,client);
        });
    }
    private:
    std::unique_ptr<TcpServer> tsvrp;
};